﻿using MongoDB.Driver;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.ClientDW.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sustainalytics.ScreeningTool.Synchronization.Caches
{
    public static class CorporateDataCollectionExtensions
    {
        public static async Task<HashSet<Guid>> GetClientSpecificCompanyIdsAsync(
            this IMongoCollection<CorporateData> collection,
            ClientFacingProduct clientFacingProduct)
        {
            var ids = new HashSet<Guid>();

            var builder = Builders<CorporateData>.Filter;
            var filter = builder.Eq(x => x.ResearchParentId, null) & !HasResearchFor(clientFacingProduct);

            var researchEntities = await collection
                .Find(filter)
                .Project(x => x.Id)
                .ToListAsync()
                .ConfigureAwait(false);

            ids.AddItems(researchEntities);

            var coverageEntities = await collection
                .Find(x => x.ResearchParentId != null && ids.Contains(x.ResearchParentId.Value))
                .Project(x => x.Id)
                .ToListAsync()
                .ConfigureAwait(false);

            ids.AddItems(coverageEntities);

            return ids;
        }

        private static FilterDefinition<CorporateData> HasResearchFor(ClientFacingProduct clientFacingProduct)
        {
            const string ClientFacingProducts = nameof(PUResearch.ClientFacingProducts);
            var builder = Builders<CorporateData>.Filter;
            var filters = typeof(CorporateData).GetProperties()
                .Where(x => x.PropertyType == typeof(PUResearch))
                .Select(x => builder.AnyEq($"{x.Name}.{ClientFacingProducts}", clientFacingProduct));
            return builder.Or(filters);
        }
    }
}
